<?php


namespace app\unify\controller;

use app\BaseController;
use app\unify\model\Menu as MenuModel;
use app\unify\model\Role as RoleModel;
use app\unify\model\RoleAuth;
use app\unify\model\User as UserModel;
use app\unify\model\UserRole;
use app\unify\validate\User as UserValidate;
use think\annotation\route\Validate;
use think\db\Query;
use think\facade\Db;
use think\facade\Log;
use think\Paginator;
use think\Request;

class User extends BaseController
{
    /**
     * 用户注册
     * @throws \Exception
     */
    #[Validate(UserValidate::class, scene: UserValidate::REGISTER)]
    public function register(Request $r): string
    {
        $param = $r->param();

        $id = UserModel::create($param)->getPk();
        if (empty($id)) {
            throw new \Exception("注册失败，请重试");
        }

        return '注册成功';
    }

    /**
     * 用户登录
     * @Author EdwardCho
     * @Date 2022/8/16
     * @Time 14:18
     * @Interface login
     * @throws \Exception
     */
    #[Validate(UserValidate::class, scene: UserValidate::LOGIN)]
    public function login(Request $r): array
    {

        $param = $r->param();

        $user = UserModel::where([
            ['username', '=', $param['username']]
        ])->findOrEmpty();

        if ($user->isEmpty()) {
            throw new \Exception('用户不存在');
        }
        Log::debug("user:" . json_encode($user, JSON_UNESCAPED_UNICODE));

        if (!UserModel::verifyPassword($param['password'], $user['password'])) {
            throw new \Exception('密码不正确');
        }

        $user->save([
            'gmt_logined' => date('Y-m-d H:i:s'),
            'logined_ip' => $r->ip()
        ]);


        return [
            'msg' => '登录成功',
            'token' => UserModel::getToken($user),
            'expired' => time() + config('jwt.ttl'),
            'homePage' => $user['homePage'],
        ];

    }

    /**
     * 修改密码
     * @Author EdwardCho
     * @Date 2022/8/16
     * @Time 14:29
     * @Interface updatePassword
     * @throws \Exception
     */
    #[Validate(UserValidate::class, scene: UserValidate::UPDATE_PASSWORD)]
    public function updatePassword(Request $r): string
    {
        $param = $r->param();

        $user = UserModel::current();

        if (!UserModel::verifyPassword($param['oldPassword'], $user['password'])) {
            throw new \Exception('旧密码错误');
        }

        if (!$user->save([
            'password' => UserModel::getHashPassword($param['password'])
        ])) {
            throw new \Exception('修改失败，请重试');
        }

        return '修改成功';
    }

    /**
     * 用户表单
     * @Author EdwardCho
     * @Date 2023/12/22
     * @Time 22:05
     * @Interface form
     */
    public function form(mixed $id = 0)
    {
        $data = [
            'status' => UserModel::STATUS_LIST,
            'roleIds' => array_column(RoleModel::where(['creator_id' => UserModel::id()])->field('name,id')->select()->toArray(), 'name', 'id'),
            'entity' => [
                'status' => UserModel::STATUS_ENABLE
            ]
        ];

        if ($id) {
            $entity = UserModel::findOrEmpty($id);
            if (empty($entity)) {
                throw new \Exception('未找到该用户');
            }
            unset($entity['password']);
            $entity['roleList'] = $entity->roles->map(fn($item) => strval($item->pivot->role_id));
            $data['entity'] = $entity;
        }

        return $data;
    }

    /**
     * 用户列表
     * @Author EdwardCho
     * @Date 2022/8/16
     * @Time 14:17
     * @Interface list
     */
    public function index(Request $r)
    {

        $where = [
            ['username', '<>', UserModel::USERNAME_ADMIN]
        ];

        //必须是我创建的角色
        $currRoleIds = RoleModel::where(['creator_id' => UserModel::id()])->column(RoleModel::getPrimaryKey());
        if (empty($currRoleIds)) {
            return Paginator::make([], $this->limit, total: 0);
        }

        $roleIds = $r->param('roleIds/a');
        if ($roleIds) {
            $currRoleIds = $roleIds;
        }

        $userIds = UserRole::where([['role_id', 'in', $currRoleIds]])->column("user_id");
        $where[] = [UserModel::getPrimaryKey(), 'in', $userIds];


        $username = $r->param('username');
        if ($username) {
            $where[] = ['username', 'LIKE', "%{$username}%"];
        }

        $nick = $r->param('nick');
        if ($nick) {
            $where[] = ['nick', 'LIKE', "%{$nick}%"];
        }

        $status = $r->param('status/a');
        if ($status) {
            $where[] = ['status', 'in', $status];
        }

        $order = "id DESC";
        $gmtLoginedOrder = $r->param('gmtLoginedOrder');
        if(in_array($gmtLoginedOrder, ['desc', 'asc'])){
            $order =  "gmt_logined {$gmtLoginedOrder}," . $order;
        }

        return UserModel::where($where)->withoutField('password')->append(['statusName'])->order($order)->with(['roles'])->paginate($this->limit)->each(function (&$item) {
            $item['roleNames'] = implode("、", $item->roles->column("name"));
            unset($item['roles']);
        });


    }

    /**
     * 当前用户信息
     * @Author EdwardCho
     * @Date 2023/11/30
     * @Time 12:53
     * @Interface current
     * @return \app\unify\model\User|array|mixed|\think\Model
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function current()
    {
        $user = UserModel::current();
        if (!$user) {
            return null;
        }

        $where = [
            ['status', '=', MenuModel::STATUS_ENABLE]
        ];

        $menuList = MenuModel::where($where)->order("serial ASC,id ASC")->with(["authIds"])->select()->each(function (&$item) {
            $item['authIds'] = $item['authIds']->column("auth_id");
        })->toArray();

        $menuList = MenuModel::toTree($menuList);


        $authIds = RoleAuth::where([
            ['role_id', 'in', $user->userRoles->column("role_id")]
        ])->column("auth_id");

        if ($user->isAdmin()) {
            $authIds = true;
        }

        $menuList = MenuModel::filterMenuTree($menuList, $authIds);


        $user['menuList'] = $menuList;

        unset($user['password']);

        return $user;
    }

    /**
     * @Notes 修改个人信息
     * @Author EdwardCho
     * @Date 2024/1/4
     * @Time 21:20
     * @Interface edit
     */
    #[Validate(UserValidate::class, scene: UserValidate::EDIT)]
    public function edit()
    {
        $params = $this->request->only(['email', 'nick', 'mobile']);
        $user = UserModel::current();
        $user->save($params);

        return '修改成功';
    }

    /**
     * 用户信息
     * @Author EdwardCho
     * @Date 2022/8/16
     * @Time 15:23
     * @Interface info
     */
    #[Validate(UserValidate::class, scene: UserValidate::READ)]
    public function read($id)
    {
        return UserModel::field('id,nick,username,status')
            ->findOrEmpty($id)->toArray();
    }

    /**
     * 添加用户
     * @Author EdwardCho
     * @Date 2022/8/16
     * @Time 14:54
     * @Interface add
     * @param \think\Request $r
     * @return string
     */
    #[Validate(UserValidate::class, scene: UserValidate::SAVE)]
    public function save(Request $r)
    {
        $param = $r->param();
        $param['platform'] = UserModel::PLATFORM_ADMIN;

        $param['creator_id'] = UserModel::id();

        Db::transaction(function () use ($param) {
            $param['password'] = UserModel::getHashPassword($param['password']);

            $user = UserModel::create($param);

            $user->roles()->saveAll($param['roleList']);
        });

        return "创建成功";
    }

    /**
     * 编辑用户
     * @Author EdwardCho
     * @Date 2022/8/16
     * @Time 14:53
     * @Interface form
     * @param \think\Request $r
     * @param mixed $id
     * @return string
     */
    #[Validate(UserValidate::class, scene: UserValidate::UPDATE)]
    public function update(Request $r, mixed $id)
    {
        $params = $r->param();

        Db::transaction(function () use ($id, $params) {
            $user = UserModel::findOrEmpty($id);
            if (empty($user)) {
                throw new \Exception('未找到该用户');
            }
            if (!empty($params['password'])) {
                $params['password'] = UserModel::getHashPassword($params['password']);
            }
            $user->save($params);

            $user->roles()->detach();

            $user->roles()->saveAll($params['roleList']);
        });

        return '修改成功';
    }

    /**
     * 退出登录
     * @Author EdwardCho
     * @Date 2022/8/16
     * @Time 14:57
     * @Interface logout
     */
    public function logout(): string
    {
        UserModel::logout();

        return '登出成功';
    }

    /**
     * 变更状态
     * @Author EdwardCho
     * @Date 2022/8/16
     * @Time 14:55
     * @Interface status
     */
    #[Validate(UserValidate::class, scene: UserValidate::UPDATE_FIELD)]
    public function updateField(array $ids, $field, $value): string
    {
        Db::transaction(function () use ($ids, $value, $field) {
            UserModel::update([
                $field => $value
            ], [
                [UserModel::getPrimaryKey(), 'in', $ids]
            ]);
        });

        return '修改成功';
    }

    /**
     * 删除账户
     * @Author EdwardCho
     * @Date 2022/8/16
     * @Time 15:32
     * @Interface del
     */
    #[Validate(UserValidate::class, scene: UserValidate::DELETE)]
    public function delete(array $ids)
    {

        Db::transaction(function () use ($ids) {
            UserModel::destroy(function (Query $q) use ($ids) {
                $q->where(UserModel::getPrimaryKey(), 'in', $ids);
            });
        });

        return '删除成功';
    }

    /**
     * 注销用户
     * @Author EdwardCho
     * @Date 2023/11/28
     * @Time 13:16
     * @Interface cancel
     */
    public function cancel()
    {
        UserModel::destroy(UserModel::id());
        return '注销成功';
    }

}